package edu.cmu.lti.function_words;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

//Function words are defined in this file with the source name

/**
 * Function word definition by Mmerriam-Webster:
 * <quote>a word (as a preposition, auxiliary verb, or conjunction) that 
 * expresses primarily a grammatical relationship</quote>
 * 
 * 
 * 
 */
public enum Source {
          
  /**
   * http://www.sequencepublishing.com
   * by Leah Gilner and Franc Morales
   */
  SEQUENCE_PUBLISHING(
  //Auxiliary Verbs
  "be able to", "can", "could", "dare", "had better", "have to", "may", 
  "might", "must", "need to", "ought", "ought to", "shall", "should", 
  "used to", "will", "would",
  //Conjunctions
  "accordingly", "after", "albeit", "although", "and", "as", "because", 
  "before", "both", "but", "consequently", "either", "for", "hence", 
  "however", "if", "neither", "nevertheless", "nor", "once", "or", 
  "since", "so", "than", "that", "then", "thence", "therefore", "tho'", 
  "though", "thus", "till", "unless", "until", "when", "whenever", "where", 
  "whereas", "wherever", "whether", "while", "whilst", "yet",
  //Determiners
  "a", "all", "an", "another", "any", "both", "each", "either", "every", 
  "her", "his", "its", "my", "neither", "no", "other", "our", "per", 
  "some", "that", "the", "their", "these", "this", "those", "whatever", 
  "whichever", "your", 
  //Prepositions
  "aboard", "about", "above", "absent", "according to", "across", 
  "after", "against", "ahead", "ahead of", "all over", "along", 
  "alongside", "amid", "amidst", "among", "amongst", "anti", "around", 
  "as", "as of", "as to", "aside", "astraddle", "astride", "at", "away from", 
  "bar", "barring", "because of", "before", "behind", "below", "beneath", 
  "beside", "besides", "between", "beyond", "but", "by", "by the time of", 
  "circa", "close by", "close to", "concerning", "considering", "despite", 
  "down", "due to", "during", "except", "except for", "excepting", 
  "excluding", "failing", "following", "for", "for all", "from", "given", 
  "in", "in between", "in front of", "in keeping with", "in place of", 
  "in spite of", "in view of", "including", "inside", "instead of", "into", 
  "less", "like", "minus", "near", "near to", "next to", "notwithstanding", 
  "of", "off", "on", "on top of", "onto", "opposite", "other than", "out", 
  "out of", "outside", "over", "past", "pending", "per", "pertaining to", 
  "plus", "regarding", "respecting", "round", "save", "saving", "similar to", 
  "since", "than", "thanks to", "through", "throughout", "thru", "till", "to", 
  "toward", "towards", "under", "underneath", "unlike", "until", "unto", 
  "up", "up to", "upon", "versus", "via", "wanting", "with", "within", 
  "without", 
  //Pronouns
  "all", "another", "any", "anybody", "anyone", "anything", "both", 
  "each", "each other", "either", "everybody", "everyone", "everything", 
  "few", "he", "her", "hers", "herself", "him", "himself", "his", 
  "I", "it", "its", "itself", "many", "me", "mine", "myself", 
  "neither", "no_one", "nobody", "none", "nothing", "one", "one another", 
  "other", "ours", "ourselves", "several", "she", "some", "somebody", 
  "someone", "something", "such", "that", "theirs", "them", "themselves", 
  "these", "they", "this", "those", "us", "we", "what", "whatever", 
  "which", "whichever", "who", "whoever", "whom", "whomever", 
  "whose", "you", "yours", "yourself", "yourselves", 
  //Quantifiers
//  "0%, 10%, 50%, 100%, etc.", 
  "0%", "10%", "50%", "100%",
//  "1, 2, 3, 4, etc.", 
  "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", 
//  "ｽ, ｼ, etc.", 
  "a bit of", "a couple of", "a few", "a good deal of", "a good many", 
  "a great deal of", "a great many", "a lack of", "a little", 
  "a little bit of", "a majority of", "a minority of", "a number of", 
  "a plethora of", "a quantity of", "all", "an amount of", "another", 
  "any", "both", "certain", "each", "either", "enough", "few", 
  "fewer", "heaps of", "less", "little", "loads", "lots", "many", 
  "masses of", "more", "most", "much", "neither", "no", "none", 
  "numbers of", 
//  "one half, one third, one fourth, one quarter, one fifth, etc.", 
  "one half", "one third", "one fourth", "one quarter", "one fifth", 
  //"one, two, three, four, etc.", 
  "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", 
  "part", "plenty of", "quantities of", 
  "several", "some", "the lack of", "the majority of", "the minority of", 
  "the number of", "the plethora of", "the remainder of", "the rest of", 
  "the whole", "tons of", "various"),
  
  /**
   * Function words for ESL students
   * http://www.flesl.net/Vocabulary/Single-word_Lists/function_word_list.php
   */
  FLESL_NET(
  //Prepositions
  "about", "across", "against", "along", "around", 
  "at", "behind", "beside", "besides", "by", 
  "despite", "down", "during", "for", "from", 
  "in", "inside", "into", "near", "of", "off", 
  "on", "onto", "over", "through", "to", "toward", 
  "with", "within", "without",
  //Pronouns
  "I", "you", "he", "me", "her", "him", "my", "mine", 
  "her", "hers", "his", "myself", "himself", "herself", 
  "anything", "everything", "anyone", "everyone", 
  "ones", "such", "it", "we", "they", "us", "them", 
  "our", "ours", "their", "theirs", "itself", "ourselves", 
  "themselves", "something", "nothing", "someone", 
  //Determiners
  "the", "some", "this", "that", "every", "all", 
  "both", "one", "first", "other", "next", "many", 
  "much", "more", "most", "several", "no", "a", "an", 
  "any", "each", "no", "half", "twice", "two", 
  "second", "another", "last", "few", "little", 
  "less", "least", 
  //Conjunctions
  "and", "but", "after", "when", "as", "because", 
  "if", "what", "where", "which", "how", "than", 
  "or", "so", "before", "since", "while", "although", 
  "though", "who", "whose", 
  //Modal Verbs
  "can", "may", "will", "shall", 
  "could", "might", "would", "should", "must", 
  //Primary Verbs
  "be", "do", "have", 
  //Adverbs
  "here", "there", "today", "tomorrow", "now", 
  "then", "always", "never", "sometimes", "usually", 
  "often", "therefore", "however", "besides", 
  "moreover", "though", "otherwise", "else", 
  "instead", "anyway", "incidentally", "meanwhile"
  ),
  
  /**
   * A Language Museum of curious and interesting uses of the English language
   * by John and Muriel Higgins
   * 
   * <quote>The lists below were originally produced for the purpose of masking 
   * selected parts of speech in the text game ECLIPSE by John and Muriel Higgins.</quote>
   * 
   * http://myweb.tiscali.co.uk/wordscape/museum/funcword.html
   */
  HIGGINS(
  //Adverbs other than manner adverbs and omitting the funny legal ones.
  "again", "ago", "almost", "already", "also", "always", "anywhere", 
  "back", "else", "even", "ever", "everywhere", "far", "hence", "here", 
  "hither", "how", "however", "near", "nearby", "nearly", "never", "not", 
  "now", "nowhere", "often", "only", "quite", "rather", "sometimes", 
  "somewhere", "soon", "still", "then", "thence", "there", "therefore", 
  "thither", "thus", "today", "tomorrow", "too", "underneath", "very", 
  "when", "whence", "where", "whither", "why", "yes", "yesterday", "yet",
  //Auxiliary verbs (including contractions)
  "am", "are", "aren't", "be", "been", "being", "can", "can't", "could", 
  "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "done", 
  "don't", "get", "gets", "getting", "got", "had", "hadn't", "has", "hasn't", 
  "have", "haven't", "having", "he'd", "he'll", "he's", "i'd", "i'll", 
  "i'm", "is", "i've", "isn't", "it's", "may", "might", "must", "mustn't", 
  "ought", "oughtn't", "shall", "shan't", "she'd", "she'll", "she's", 
  "should", "shouldn't", "that's", "they'd", "they'll", "they're", "was", 
  "wasn't", "we'd", "we'll", "were", "we're", "weren't", "we've", "will", 
  "won't", "would", "wouldn't", "you'd", "you'll", "you're", "you've",
  //Prepositions/Conjunctions (one category since there is some overlap)
  "about", "above", "after", "along", "although", "among", "and", "around", 
  "as", "at", "before", "below", "beneath", "beside", "between", "beyond", 
  "but", "by", "down", "during", "except", "for", "from", "if", "in", 
  "into", "near", "nor", "of", "off", "on", "or", "out", "over", "round", 
  "since", "so", "than", "that", "though", "through", "till", "to", 
  "towards", "under", "unless", "until", "up", "whereas", "while", "with", 
  "within", "without",
  //Determiners/Pronouns (omitting archaic THOU, THEE, etc)
  "a", "all", "an", "another", "any", "anybody", "anything", "both", 
  "each", "either", "enough", "every", "everybody", "everyone", "everything", 
  "few", "fewer", "he", "her", "hers", "herself", "him", "himself", "his", 
  "i", "it", "its", "itself", "less", "many", "me", "mine", "more", "most", 
  "much", "my", "myself", "neither", "no", "nobody", "none", "noone", 
  "nothing", "other", "others", "our", "ours", "ourselves", "she", "some", 
  "somebody", "someone", "something", "such", "that", "the", "their", 
  "theirs", "them", "themselves", "these", "they", "this", "those", "us", 
  "we", "what", "which", "who", "whom", "whose", "you", "your", "yours", 
  "yourself", "yourselves",
  //Numbers
  "billion", "billionth", "eight", "eighteen", "eighteenth", "eighth", 
  "eightieth", "eighty", "eleven", "eleventh", "fifteen", "fifteenth", 
  "fifth", "fiftieth", "fifty", "first", "five", "fortieth", "forty", 
  "four", "fourteen", "fourteenth", "fourth", "hundred", "hundredth", "last", 
  "million", "millionth", "next", "nine", "nineteen", "nineteenth", 
  "ninetieth", "ninety", "ninth", "once", "one", "second", "seven", 
  "seventeen", "seventeenth", "seventh", "seventieth", "seventy", "six", 
  "sixteen", "sixteenth", "sixth", "sixtieth", "sixty", "ten", "tenth", 
  "third", "thirteen", "thirteenth", "thirtieth", "thirty", "thousand", 
  "thousandth", "three", "thrice", "twelfth", "twelve", "twentieth", "twenty", 
  "twice", "two"
  ),
  
  /**
   * Nation, I.S.P., 2001, Learning Vocabulary in Another Language, Cambridge Applied Linguistics.
   * (Cited from http://www.um.es/lacell/aelinco/contenido/pdf/15.pdf)
   */
  NATION(
  //ADVERBIAL PARTICLES
  "again", "ago", "almost", "already", "also", "always", "anywhere", 
  "back", "else", "even", "ever", "everywhere", "far", "hence", "here", 
  "hither", "how", "however", "near", "nearby", "nearly", "never", "not", 
  "now", "nowhere", "often", "only", "quite", "rather", "sometimes", 
  "somewhere", "soon", "still", "then", "thence", "there", "therefore", 
  "thither", "thus", "today", "tomorrow", "too", "underneath", "very", 
  "when", "whence", "where", "whither", "why", "yes", "yesterday", "yet",
  //AUXILIARY VERBS
  "am", "are", "aren't", "be", "been", "being", "can", "can't", "could", 
  "couldn't", "did", "didn't", "do", "does", "doesn't", "doing", "done", 
  "don't", "get", "gets", "getting", "got", "had", "hadn't", "has", "hasn't", 
  "have", "haven't", "having", "he'd", "he'll", "he's", "I'd", "I'll", 
  "I'm", "is", "I've", "isn't", "it's", "may", "might", "must", "mustn't", 
  "ought", "oughtn't", "shall", "shan't", "she'd", "she'll", "she's", 
  "should", "shouldn't", "that's", "they'd", "they'll", "they're", "was", 
  "wasn't", "we'd", "we'll", "were", "we're", "weren't", "we've", "will", 
  "won't", "would", "wouldn't", "you'd", "you'll", "you're", "you've",
  //PREPOSITIONS/CONJUNCTIONS
  "about", "above", "after", "along", "although", "among", "and", "around", 
  "as", "at", "before", "below", "beneath", "beside", "between", "beyond", 
  "but", "by", "down", "during", "except", "for", "from", "if", "in", "into", 
  "near", "nor", "of", "off", "on", "or", "out", "over", "round", "since", 
  "so", "than", "that", "though", "through", "till", "to", "towards", 
  "under", "unless", "until", "up", "whereas", "while", "with", "within", 
  "without",
  //DETERMINERS/PRONOUNS
  "a", "all", "an", "another", "any", "anybody", "anything", "both", 
  "each", "either", "enough", "every", "everybody", "everyone", 
  "everything", "few", "fewer", "he", "her", "hers", "herself", "him", 
  "himself", "his", "I", "it", "its", "itself", "less", "many", "me", 
  "mine", "more", "most", "much", "my", "myself", "neither", "no", "nobody", 
  "none", "no-one", "nothing", "other", "others", "our", "ours", "ourselves", 
  "she", "some", "somebody", "someone", "something", "such", "that", 
  "the", "their", "theirs", "them", "themselves", "these", "they", "this", 
  "those", "us", "we", "what", "which", "who", "whom", "whose", "you", 
  "your", "yours", "yourself", "yourselves"
  ),
  
  //Depending on a tokenizer, the following ones may appear as a word
  SHIMA(
  "'", "s", "'s", "n", "'n", "d", "'d", "t", "'t", 
  "m", "'m", "ll", "'ll", "re", "'re", "ve", "'ve", 
  "null", "zero", "dozen"
  );
  
  private String[] functionWords;
  
  private Source( String ... functionWords ) {
    this.functionWords = functionWords;
  }
  
  public Set<String> getFunctionWords() {
    return new LinkedHashSet<String>(Arrays.asList(functionWords));
  }
  public Set<String> getFunctionWordsInLowercase() {
    Set<String> words = new LinkedHashSet<String>(functionWords.length);
    for (String word : functionWords) {
      words.add( word.toLowerCase() );
    }
    return words;
  }
  
  public static void printStat() {
    Map<Source,Set<String>> allWords = new HashMap<Source,Set<String>>();
    Map<Source,Set<String>> uniqueWords = new HashMap<Source,Set<String>>();
    Set<String> allWordsAcrossSources = new LinkedHashSet<String>();
    StringBuilder report = new StringBuilder();
    for (Source s : Source.values()) {
      Set<String> words = s.getFunctionWordsInLowercase();
      allWords.put(s, words);
      uniqueWords.put(s, new HashSet<String>());
      allWordsAcrossSources.addAll(words);
    }
    for ( String word : allWordsAcrossSources ) {
      Set<Source> sourceContainingTheWord = new HashSet<Source>();
      for ( Source s : Source.values() ) {
        if (allWords.get(s).contains(word.toLowerCase())) {
          sourceContainingTheWord.add(s);
        }
      }
      if (sourceContainingTheWord.size()==1) {
        uniqueWords.get(sourceContainingTheWord.iterator().next()).add(word);
      }
    }
    for ( Source s : Source.values() ) {
      report.append(s+" contains "+allWords.get(s).size()+" words, with "+uniqueWords.get(s).size()+" unique words:\n");
      report.append("\t"+uniqueWords.get(s)+"\n");
    }
    System.out.println(report);
  }
  
}
